package com.demo.rest;

import com.demo.listener.message.Order;
import com.demo.util.IdWorker;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.ExecutionException;

/**
 * 订单相关操作
 *
 * @author jie.luo
 * @since 2021/3/1
 */
@RestController
@RequestMapping("/order")
public class OrderRest {

    private static final Logger LOGGER = LoggerFactory.getLogger(OrderRest.class);

    private RabbitTemplate rabbitTemplate;
    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    public void setRabbitTemplate(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
        // 消息异步确认
        /*this.rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @SneakyThrows
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if (ack) {
                    LOGGER.debug("消息确认: {} , {}", correlationData.getId(), objectMapper.readValue(correlationData.getReturnedMessage().getBody(), Order.class));
                } else {
                    LOGGER.error("消息确认失败：{}", cause);
                }
            }
        });*/
    }

    @GetMapping
    public Long order(@RequestParam(name = "userId") Long userId) throws ExecutionException, InterruptedException {
        Order order = new Order();
        order.setOrderId(IdWorker.id());
        order.setUserId(userId);

        CorrelationData correlationData = new CorrelationData();

        // 发送下单消息，数据入库
        rabbitTemplate.convertAndSend("order.exchange", "order.key", order, correlationData);

        // 同步确认消息
        CorrelationData.Confirm confirm = correlationData.getFuture().get();
        boolean ack = confirm.isAck();
        if (ack) {
            LOGGER.debug("同步消息确认....");
        } else {
            LOGGER.error("同步消息确认失败");
        }

        // 发送延时队列，用于支付超时取消订单
        rabbitTemplate.convertAndSend("order.exchange.ttl", "order.key.ttl", order.getOrderId(), correlationData);

        return order.getOrderId();
    }

    @GetMapping("/pay")
    public String pay(@RequestParam(name = "orderId") Long orderId) {

        // 订单状态修改为已支付
        System.out.println("订单状态修改为已支付: " + orderId);

        return "SUCCESS";
    }

    /**
     * 延迟队列案例
     */
    @GetMapping("/place")
    public String order(@RequestParam(name = "userId") Long userId, @RequestParam(name = "orderId") Long orderId) throws JsonProcessingException, ExecutionException, InterruptedException {

        Order order = new Order();
        order.setOrderId(orderId);
        order.setUserId(userId);

        CorrelationData correlationData = new CorrelationData();

        rabbitTemplate.convertAndSend("order.ex", "key.order", order, message -> {
            message.getMessageProperties().setHeader("x-delay", 10 * 1000);
            return message;
        }, correlationData);

        // 同步确认消息
        CorrelationData.Confirm confirm = correlationData.getFuture().get();
        boolean ack = confirm.isAck();
        if (ack) {
            LOGGER.debug("同步消息确认....");
        } else {
            LOGGER.error("同步消息确认失败");
        }

        return "SUCCESS";
    }

}
